package at.com.vn.chess.applet;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JPanel;

import vn.com.bip.office.smart.util.XMLHelper;
import vn.nnn.shogi.board.Board;
import vn.nnn.shogi.board.HistoryButtonLayout;
import vn.nnn.shogi.quanco.ListQuanCoStatus;
import vn.nnn.shogi.quanco.QuanCo;
import at.com.vn.chess.element.HistoryButton;
import at.com.vn.chess.element.PlayerInfoArea;
import at.com.vn.chess.element.PrivateChatPanel;
import at.com.vn.chess.element.StopWatch;
import at.com.vn.chess.entity.ChatUser;
import at.com.vn.chess.entity.ChessBoardInfo;
import at.com.vn.chess.entity.PlayersInfo;
import at.com.vn.chess.listener.ChatListener;
import at.com.vn.chess.listener.ChessTableListener;
import at.com.vn.chess.listener.TimerListener;
import at.com.vn.chess.network.ClientUtil;
import at.com.vn.chess.util.Const;
import at.com.vn.chess.util.Msg;

public class ChessPanel extends JPanel implements Runnable {

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	// Common element
	private String url_servlet;
	private Thread thread;
	// TODO
	private ChessTableListener mListener;
	private String playerName = "Mr X";
	private String roomId;
	private int tableId = 0;
	private int isTablesOwner = Const.FALSE;
	private ClientUtil clientUtil;
	private ChatUser user;

	private int player1RemainTime;
	private int player2RemainTime;

	private StopWatch player1Timer;
	private StopWatch player2Timer;
	private String player1Name = "nghi", player2Name = "nhai";


	// Button element
	private JButton btNext;
	private JButton btPrevious;
	private JButton btBegin;
	private JButton btCurrent;

	private JButton btInOut;
	private PrivateChatPanel chatPanel;

	// Chess element
	// Quan co
	private ListQuanCoStatus listQuanCoStatus;
	private ArrayList<QuanCo> listQuanCo;
	private Board board;
	private PlayerInfoArea playerInfoArea;

	private int idxChosen; // this identifies which piece to move
	private QuanCo pieceChosen;
	private int whosTurn;
	private int playerColor;
	private boolean isPlayer;
	private int whosWon;

	private String message = "";

	private String status;
	private int thisTurnIsPlayer2sTurn;

	private ArrayList<Rectangle> historyForRepaint;

	private String initStatus;

	// Flag
	private boolean readyToMove; // this is for seeing if its ok to move
	private boolean showHistoryFlag;
	private boolean becomeAViewer;
	private boolean normalDirection;
	private boolean onGameFlag;

	JApplet mainApplet;

	public ChessPanel( String title, String strURL, String userName,
			String roomID, int tableID, JApplet mainApplet ) {

		// Set kich thuoc cho dialog
		setSize( Const.DIALOG_WIDTH, Const.DIALOG_HEIGHT );
		setLayout(null);

		// Get parameter from web
		this.url_servlet = strURL;
		this.roomId = roomID;
		this.tableId = tableID;
		playerName = userName;
		this.mainApplet = mainApplet;
		normalDirection = true;

		// Layout chung cho ban co
		board = new Board( getSize() );

		// Thong tin ve nguoi choi
		user = new ChatUser();

		user.setUserID( playerName );
		user.setRoomID( roomId );
		user.setChatMsg( message );
		user.setIsActive( Const.TRUE );
		user.setPrivateRoomID( tableId );
		user.setIsDeleted( Const.FALSE );

		// Tao mot doi tuong giao tiep voi server
		clientUtil = new ClientUtil( mainApplet.getCodeBase(), url_servlet,
				playerName, roomId, tableId );

		status = Const.STATUS_IDLE;

		// Khoi tao cac bien
		initTrangThaiBanCo();

		// Khoi tao vung chat
		initPrivateChatArea();

		// Khoi tao cac nut xem lai lich su ban co
		initShowHistoryButtonArea();

		// Khoi tao quan co
		initBanCo();

		showHistoryFlag = false;
		becomeAViewer = false;

		// Bat dau thread moi
		startThisThread();

		String xmlMsg = chatPanel.prepareChatMsg( Const.PROCESS_CHAT_PRIVATE_JOIN, " has joined..." );
		chatPanel.showResult( clientUtil.doPrivateData( xmlMsg ) );

		// Gui thong tin trang thai cua ban co
		String xml = initStatus;
		System.out.println(xml);
		String history = listQuanCoStatus
				.convertToXMLString( Const.PROCESS_PLAY_SHOGI_GET_HISTORY, user, status, whosTurn, whosWon );
		try {
			xml = clientUtil.doPrivateData( initStatus );
			history = clientUtil.doPrivateData( history );

			// Tach chuoi lich su thanh list
			if ( history == null || history.isEmpty() ) {
				System.out.println( getClass().getSimpleName() + " : Loi null" );
				return;
			}
			
//			if (!(history == null || history.isEmpty())) {
				String[] array = history.split( Const.SEPERATE_MARK_OF_HISTORY );
				
				for ( int i = 0; i < array.length; i++ ) {
					listQuanCoStatus.addHistory( array[i] );
				}
				
				// For Test
				System.out.println( this.getClass().getSimpleName()
						+ "-init: getCurrentStep: " + listQuanCoStatus.getStep() );				
//			}
		} catch ( Exception e ) {
			System.out.println( e.getMessage() );
		}

		// Tai hien lai trang thai hien hanh cua ban co
		@SuppressWarnings( "unchecked" )
		ArrayList<ChessBoardInfo> listInfo = ( ArrayList<ChessBoardInfo> ) XMLHelper
				.convertXMLToListObject( xml, ChessBoardInfo.class );

		status = listInfo.get( 0 ).getStatus();

		player1Name = listInfo.get( 0 ).getBName();
		player2Name = listInfo.get( 0 ).getWName();

		playerInfoArea.setPlayer1Name( player1Name );
		playerInfoArea.setPlayer2Name( player2Name );

		if( !player1Name.isEmpty() && !player2Name.isEmpty() ) {
			btInOut.setEnabled( false );
		}

		if ( !isPlayer && status.equals( Const.STATUS_RUN ) ) {
			whosTurn = listInfo.get( 0 ).getTurn();
			becomeAViewer = true;
			listQuanCoStatus.taiHienListQuanCo( listInfo, true );
		} else {
			synchronizeBoardStatus( xml );
		}

		clientUtil.sendBroadcastMessage( xmlMsg );
		repaint();
	}

	private void initPrivateChatArea() {
		chatPanel = new PrivateChatPanel( board, user );
		add( chatPanel );
		Point offset = board.getPrivateChatLocation();
		Rectangle bound = new Rectangle( offset, board.getPrivateChatAreaSize() );
		chatPanel.setBounds( bound );

		chatPanel.setOnChatListner( new ChatListener() {

			@Override
			public void chat( String xmlMsg ) {
				clientUtil.sendBroadcastMessage( xmlMsg );
			}
		});
	}

	public void setOnCloseListener( ChessTableListener listener ) {
		// TODO
		mListener = listener;
	}

	@Override
	public void paintComponent( Graphics g ) {

		// Ve ban co
		Image bgImage = createImageIcon("banco.png", "anh nen").getImage();
//		Image bgImage = mainApplet.getImage( mainApplet.getCodeBase(), Const.BACKGROUND_IMAGE );
//		g.drawImage( bgImage, 0, 0, bgImage.getWidth( mainApplet ), bgImage.getHeight( mainApplet ), mainApplet);
		g.drawImage( bgImage, 0, 0, getSize().width, getSize().height, mainApplet);

		// Ve toan cac quan co
		if( !showHistoryFlag ) {
			listQuanCoStatus.drawListQuanCo( g, readyToMove );

		}else {
			listQuanCoStatus.drawListQuanCoForHistory( g, this );
		}

		// Nếu hết cờ thì hiển thị message ở giữa bàn cờ
		if ( status.equals( Const.STATUS_END ) ) {
			board.drawMessage( g, message );
		}

		// Ve vung bao quanh khi chon quan co
		if ( readyToMove ) {
			g.setColor( Color.green );
			g.drawRect( pieceChosen.getX(), pieceChosen.getY(), pieceChosen
					.getWidth(), pieceChosen.getHeight() );
		}
	}

	protected ImageIcon createImageIcon(String path,
            String description) {
		java.net.URL imgURL = getClass().getResource(path);
		if (imgURL != null) {
		return new ImageIcon(imgURL, description);
		} else {
		System.err.println("Couldn't find file: " + path);
		return null;
		}
		}

	class MousePressListener extends MouseAdapter {

		private boolean moved;

		// Xu ly su kien khi nhan chuot
		@Override
		public void mousePressed( MouseEvent event ) {

			if( !showHistoryFlag ) {

				// Lấy vị trí đã chọn trên bàn cờ
				Rectangle oDangChon = board.getODangChon( event.getX(), event.getY() );

				// Trường hợp này là khi đã phân định thắng thua, muốn chơi lại từ đầu
				if ( status.equals( Const.STATUS_END ) ) {
					// Neu click ben trong ban co thi choi lai tu dau
					if ( isPlayer && board.isInRealBoard( oDangChon ) ) {
						initTrangThaiBanCo();
						String resetBoardStatus = listQuanCoStatus.getInitStatusOfBoard( Const.PROCESS_PLAY_SHOGI_PLAY, user, player1Name, player2Name );
						clientUtil.sendBroadcastMessage( resetBoardStatus );
					}
				}
				// Trong lúc đánh cờ
				else {
					if ( isPlayer ) {
						operateWhenMousePressed( oDangChon );
					}
				}
			}
		}

		/**
		 * @param oDangChon
		 */
		private void operateWhenMousePressed( Rectangle oDangChon ) {

			ArrayList<QuanCo> beforeStatus = new ArrayList<QuanCo>();
			if ( readyToMove ) {

				readyToMove = false;

				beforeStatus = listQuanCoStatus.clone();

				// move Piece
				moved = listQuanCoStatus
						.moveAPiece( idxChosen, oDangChon, getParent() );

			}
			// when ok = false we look for a piece
			else {
				moved = false;

				//				idxChosen = listQuanCoStatus.selectAPiece( oDangChon );

				if ( status.equals( Const.STATUS_IDLE ) ) {
					idxChosen = listQuanCoStatus
							.selectAPiece( oDangChon, QuanCo.QUAN_DEN );
				} else if ( status.equals( Const.STATUS_WAIT ) && playerColor == Const.UNDEFINE_VALUE ) {
					// Truong hop nuoc di quan thu 2
					idxChosen = listQuanCoStatus
							.selectAPiece( oDangChon, QuanCo.QUAN_TRANG );
				} else if ( status.equals( Const.STATUS_RUN ) && isPlayer
						&& playerColor == whosTurn ) {
					idxChosen = listQuanCoStatus
							.selectAPiece( oDangChon, whosTurn );
				}

				if ( idxChosen != Const.UNDEFINE_VALUE ) {
					readyToMove = true;
					pieceChosen = listQuanCo.get( idxChosen );
				}
			}

//			repaint( listQuanCoStatus.getRepaintArea() );
			repaint();

			// Sau khi di chuyen thi thay doi luot di va gui du lieu len server
			if ( moved ) {

				// Neu bat dau vao van co va di nuoc dau tien
				if ( !status.equals( Const.STATUS_RUN ) ) {
					playerColor = pieceChosen.color;
					whosTurn = playerColor;
					if ( status.equals( Const.STATUS_IDLE ) ) {
						status = Const.STATUS_WAIT;
					} else if ( status.equals( Const.STATUS_WAIT ) ) {
						status = Const.STATUS_RUN;
					}

					// TODO
					mListener.setPlayerClicked( playerName, playerColor, status );
				}

				// Kiem tra chieu het
				int whichSide;
				if ( pieceChosen.color == QuanCo.QUAN_DEN ) {
					whichSide = QuanCo.QUAN_TRANG;
				} else {
					whichSide = QuanCo.QUAN_DEN;
				}

				if ( listQuanCoStatus.isHetCo( whichSide ) ) {
					status = Const.STATUS_END;
					whosWon = playerColor;
				}

				// Reset trạng thái chọn quân
				idxChosen = Const.UNDEFINE_VALUE;
				pieceChosen = null;

				// Thay đổi lượt đánh
				changeTurn();

				// Lay thoi gian con lai cua nguoi choi co
				if( status.equals( Const.STATUS_RUN ) ) {
					if( isTablesOwner == Const.TRUE ) {
						player1RemainTime = player1Timer.getRemainTime();
					}else {
						player2RemainTime = player2Timer.getRemainTime();
					}
				}

				// Gửi toàn bộ trạng thái bàn cờ lên server
				String mess = listQuanCoStatus
						.convertToXMLString( Const.PROCESS_PLAY_SHOGI_PLAY, user, isTablesOwner, status, whosTurn, player1Name, player2Name, player1RemainTime, player2RemainTime, whosWon );

				if( playerColor == QuanCo.QUAN_DEN ) {
					listQuanCoStatus.createListHistory( mess, beforeStatus, true );
				}else {
					listQuanCoStatus.createListHistory( mess, beforeStatus, false );

					// Neu la quan trang thi dao nguoc lai ban co truoc khi gui len server
					mess = listQuanCoStatus
					.convertSymmetryBoardToXMLString( Const.PROCESS_PLAY_SHOGI_PLAY, user, isTablesOwner, status, whosTurn, player1Name, player2Name, player1RemainTime, player2RemainTime, whosWon );
				}

				// Gui len server
				clientUtil.sendBroadcastMessage( mess );
			}

		}

		private void changeTurn() {
			if ( whosTurn == QuanCo.QUAN_TRANG ) {
				whosTurn = QuanCo.QUAN_DEN;
			} else {
				whosTurn = QuanCo.QUAN_TRANG;
			}
		}
	}

	@Override
	public void run() {

		Thread thisThread = Thread.currentThread();
		while ( thread == thisThread ) {
			try {
				Thread.sleep( Const.ONE_SECOND );
			} catch ( InterruptedException e ) {
				System.out.println( "Loi ngat ket noi" );
			}

			// Lấy message từ server về
			String recivedXML = clientUtil.receiverMessage();

			if ( !recivedXML.isEmpty() ) {

				boolean playShogiFlag = true;
				String xmlUser;
				String xmlBoard = recivedXML;

				// Neu thoat khoi ban co
				if ( recivedXML.contains( Const.SERVICE_LEAVE_SHOGI ) ) {

					String[] str = xmlBoard.split( Const.SEPERATE_MARK_FOR_LEAVE );

					xmlBoard = str[0];
					xmlUser = str[1];

					chatPanel.showResult( xmlUser );
				}

				// Neu chat chit
				else if ( recivedXML.contains( Const.SERVICE_CHAT_PRIVATE ) ) {
					playShogiFlag = false; // Khong tai hien lai ban co
					xmlUser = recivedXML;

					chatPanel.showResult( xmlUser );
				}

				// Neu ngoi vao ban co
				else if( recivedXML.contains( Const.PROCESS_PLAY_SHOGI_SIT_TO_TABLE ) ) {
					playShogiFlag = false; // Khong tai hien lai ban co

					PlayersInfo playersInfo = ( PlayersInfo ) XMLHelper
							.convertXMLToListObject( recivedXML, PlayersInfo.class )
							.get( 0 );

					if( playersInfo.getRId().equals( roomId ) && playersInfo.getTId() == tableId ) {
						player1Name = playersInfo.getPlayer1Name();
						player2Name = playersInfo.getPlayer2Name();

						playerInfoArea.setPlayer1Name( playersInfo.getPlayer1Name() );
						playerInfoArea.setPlayer2Name( playersInfo.getPlayer2Name() );
					}
				}

				// Neu dang danh co ma thoat ra ngoai
				else if( recivedXML.contains( Const.PROCESS_PLAY_SHOGI_LEFT_TO_TABLE ) ) {
					playShogiFlag = false; // Khong tai hien lai ban co

					PlayersInfo playersInfo = ( PlayersInfo ) XMLHelper
							.convertXMLToListObject( recivedXML, PlayersInfo.class )
							.get( 0 );

					if( playersInfo.getRId().equals( roomId ) && playersInfo.getTId() == tableId ) {
						player1Name = playersInfo.getPlayer1Name();
						player2Name = playersInfo.getPlayer2Name();

						if( isPlayer ) {
							isTablesOwner = Const.TRUE;
						}

						playerInfoArea.setPlayer1Name( playersInfo.getPlayer1Name() );
						playerInfoArea.setPlayer2Name( playersInfo.getPlayer2Name() );

						status = Const.STATUS_END;
						whosWon = playersInfo.getWhosWon();
						doEnd();
						repaint( listQuanCoStatus.getRepaintArea() );
					}
				}

				// Neu thang thua vi het gio
				else if( recivedXML.contains( Const.PROCESS_PLAY_SHOGI_WIN_LOSE_ACTION ) ) {
					playShogiFlag = false; // Khong tai hien lai ban co

					PlayersInfo playersInfo = ( PlayersInfo ) XMLHelper
							.convertXMLToListObject( recivedXML, PlayersInfo.class )
							.get( 0 );

					if( playersInfo.getRId().equals( roomId ) && playersInfo.getTId() == tableId ) {
						status = Const.STATUS_END;
						whosWon = playersInfo.getWhosWon();
						doEnd();
						repaint( listQuanCoStatus.getRepaintArea() );
					}
				}

				// Neu reset lai ban co vi co nguoi thoat ra
				else if( recivedXML.contains( Const.PROCESS_PLAY_SHOGI_RESET_BOARD ) ) {
					ChessBoardInfo boardInfo = ( ChessBoardInfo ) XMLHelper
							.convertXMLToListObject( recivedXML, ChessBoardInfo.class )
							.get( 0 );

					if ( boardInfo.getRId().equals( roomId ) && boardInfo.getTId() == tableId ) {

						player1Name = boardInfo.getBName();
						player2Name = boardInfo.getWName();

						if( isPlayer ) {
							isTablesOwner = Const.TRUE;
						}

						playerInfoArea.setPlayer1Name( player1Name );
						playerInfoArea.setPlayer2Name( player2Name );
					}
				}

				// Neu khong phai la co mot su kien nguoi xem thoat khoi ban co
				// thi tiep tuc xu ly
				// Neu la danh co
				if ( playShogiFlag ) {

					@SuppressWarnings( "unchecked" )
					ArrayList<ChessBoardInfo> listInfo = ( ArrayList<ChessBoardInfo> ) XMLHelper
							.convertXMLToListObject( xmlBoard, ChessBoardInfo.class );

					if ( !listInfo.isEmpty() ) {
						String room = listInfo.get( 0 ).getRId();
						int table = listInfo.get( 0 ).getTId();

						if ( room.equals( roomId ) && table == tableId ) {
							synchronizeBoardStatus( listInfo );

							// TODO Xoa di sau khi xong
//							listQuanCoStatus.testShowHistoryString();
						}
					}
				}
			} else {
				System.out.println( "Server khong tra ve chuoi xml" );
			}
		}

	}

	private void initShowHistoryButtonArea() {
		HistoryButtonLayout historyLayout = new HistoryButtonLayout(
				board.getHistoryButtonLocation() );

		btBegin = new HistoryButton( "|<<", historyLayout.getBeginBtBound() );
		btPrevious = new HistoryButton( "<<",
				historyLayout.getPreviousBtBound() );
		btNext = new HistoryButton( ">>", historyLayout.getNextBtBound() );
		btCurrent = new HistoryButton( ">>|",
				historyLayout.getCurrentBtBound() );

		btInOut = new HistoryButton( Const.BUTTON_LABEL_NHAP,
				historyLayout.getBt1Bound() );

		if( status.equals( Const.STATUS_RUN ) ) {
			onGameFlag = false;
			btInOut.setEnabled( false );
		}

		add( btBegin );
		add( btPrevious );
		add( btNext );
		add( btCurrent );
		add( btInOut );

		btBegin.addActionListener( new ActionListener() {

			@Override
			public void actionPerformed( ActionEvent e ) {
				listQuanCoStatus.setHistoryInInitStatus();

				if ( !showHistoryFlag ) {
					changeToViewHistoryMode();
				}

				repaint( board.getRepaintOnlyActiveBoard() );
			}
		} );

		btPrevious.addActionListener( new ActionListener() {

			@Override
			public void actionPerformed( ActionEvent e ) {
				if ( listQuanCoStatus.getStep() >= 0 ) {

					if ( !showHistoryFlag ) {
						listQuanCoStatus.setHistoryInCurrentStatus();
						changeToViewHistoryMode();
					}

					listQuanCoStatus.showPrevious();
					repaint( listQuanCoStatus.getRepaintArea() );
				}
			}
		} );

		btNext.addActionListener( new ActionListener() {

			@Override
			public void actionPerformed( ActionEvent e ) {
				if ( listQuanCoStatus.getStep() < listQuanCoStatus.getCurrentStep() ) {
					listQuanCoStatus.showNext();

					if ( listQuanCoStatus.isCurrentStep() ) {
						changeToViewCurrentBoardMode();
					}
				}

				repaint( listQuanCoStatus.getRepaintArea() );
			}
		} );

		btCurrent.addActionListener( new ActionListener() {

			@Override
			public void actionPerformed( ActionEvent e ) {
				listQuanCoStatus.setHistoryInCurrentStatus();
				changeToViewCurrentBoardMode();
				repaint( board.getRepaintOnlyActiveBoard() );
			}
		} );

		btInOut.addActionListener( new ActionListener() {

			@Override
			public void actionPerformed( ActionEvent e ) {
				if( !onGameFlag ) {
					isPlayer = true;
					onGameFlag = true;
					btInOut.setText( Const.BUTTON_LABEL_XUAT );

					// Set ten tren ban co
					if( player1Name.isEmpty() ) {
						player1Name = playerName;
						isTablesOwner = Const.TRUE;
					}else {
						player2Name = playerName;
						isTablesOwner = Const.FALSE;
					}

					PlayersInfo playerInfo = new PlayersInfo( roomId, tableId, player1Name, player2Name, isTablesOwner );

					String xml = XMLHelper.convertListObjectToXML( playerInfo, Const.PROCESS_PLAY_SHOGI_SIT_TO_TABLE, PlayersInfo.class );
					clientUtil.sendBroadcastMessage( xml );
				}else {
					processWinLoseWhenExit();
				}
			}
		} );
	}

	private void initBanCo() {

		initListQuanCoStatus( normalDirection );

		initStatus = listQuanCoStatus.getInitStatusOfBoard( Const.PROCESS_PLAY_SHOGI_JOIN, user, status, player1Name, player2Name, whosTurn, whosWon );

		historyForRepaint = listQuanCoStatus.getHistory();

		/*
		 * START - Add thong tin ve nguoi choi va dong ho dem nguoc cua tung nguoi
		 */
		playerInfoArea = new PlayerInfoArea( board );

		add( playerInfoArea.getLblPlayer1Name() );
		add( playerInfoArea.getLblPlayer2Name() );

		player1Timer = playerInfoArea.getGlobalPlayer1StopWatch();
		add( player1Timer );

		player2Timer = playerInfoArea.getGlobalPlayer2StopWatch();
		add( player2Timer );

		// add listener
		player1Timer.addTimeZeroListener( stopWatchListener );
		player2Timer.addTimeZeroListener( stopWatchListener );
		/*
		 * FINISH - Add thong tin ve nguoi choi va dong ho dem nguoc cua tung nguoi
		 */

		addMouseListener( new MousePressListener() );
	}

	private void initListQuanCoStatus( boolean normalDirection ) {
		// Khoi tao quan co
		listQuanCoStatus = new ListQuanCoStatus( roomId, tableId, board, normalDirection,
				mainApplet );
		listQuanCo = listQuanCoStatus.getListQuanCo();
	}


	private void initTrangThaiBanCo() {
		readyToMove = false; // this is for seeing if its ok to move
		idxChosen = Const.UNDEFINE_VALUE; // this identifies which piece to move
		whosTurn = Const.UNDEFINE_VALUE;
		playerColor = Const.UNDEFINE_VALUE;
		pieceChosen = null;
		whosWon = Const.UNDEFINE_VALUE;
		becomeAViewer = false;

		player1RemainTime = Const.COUNT_DOWN_START_POINT_TOTAL;
		player2RemainTime = Const.COUNT_DOWN_START_POINT_TOTAL;
	}

	private void startThisThread() {
		thread = new Thread( this );
		thread.start();
	}

	public void destroy() {

		if( isPlayer ) {
			processWinLoseWhenExit();			
		}else {
//			String xml = listQuanCoStatus
//					.convertToXMLString( Const.PROCESS_LEAVE_SHOGI_LEFT, user, isTablesOwner, status, whosTurn, player1Name, player2Name, player1RemainTime, player2RemainTime, whosWon );
			user.setChatMsg("has left...");
			String xml = XMLHelper.convertListObjectToXML(user, Const.PROCESS_CHAT_PRIVATE_LEFT, ChatUser.class);

			clientUtil.sendBroadcastMessage( xml );
		}		
	}

	/**
	 * @param xml
	 */
	private void synchronizeBoardStatus( String xml ) {

		@SuppressWarnings( "unchecked" )
		ArrayList<ChessBoardInfo> listInfo = ( ArrayList<ChessBoardInfo> ) XMLHelper
				.convertXMLToListObject( xml, ChessBoardInfo.class );

		synchronizeBoardStatus( listInfo );
	}

	private void synchronizeBoardStatus( ArrayList<ChessBoardInfo> listInfo ) {

		// Tai hien lai vi tri cac quan co tren ban co
		// Xu ly de tai hien ban co
		ChessBoardInfo info = listInfo.get( 0 );
		whosTurn = info.getTurn();
		status = info.getStatus();
		whosWon = info.getWhosWon();
		thisTurnIsPlayer2sTurn = info.getIsTOwner();
		player1RemainTime = info.getBRemainT();
		player2RemainTime = info.getWRemainT();

		boolean taiHienBanCoFlag = true;
		if ( status.equals( Const.STATUS_RUN ) ) {
			doRunning();
		} else if ( status.equals( Const.STATUS_IDLE ) ) {
			doInitOrReset();
			taiHienBanCoFlag = false;
		} else if ( status.equals( Const.STATUS_END ) ) {
			doEnd();
			taiHienBanCoFlag = false;
		}

		if( taiHienBanCoFlag ) {
			taiHienBanCo( listInfo );
		}
	}

	private void taiHienBanCo( ArrayList<ChessBoardInfo> listInfo ) {

		boolean taiHienFlag = true;
		boolean symmetryFlag = false;
		if ( playerColor != Const.UNDEFINE_VALUE ) { // Nếu là game thủ
			if ( whosTurn == playerColor ) { // Nếu không phải là client vừa đi quân
				if ( playerColor == QuanCo.QUAN_TRANG ) { // Nếu game thủ là quân trắng
					symmetryFlag = true;

					// Dao nguoc vi tri quan co trong list
					ArrayList<ChessBoardInfo> listInfo2 = new ArrayList<ChessBoardInfo>();

					for( int i = listInfo.size() - 1; i >= 0; i-- ) {
						listInfo2.add( listInfo.get( i ) );
					}

					listInfo = listInfo2;
				}
			} else {
				taiHienFlag = false;
			}
		} else if ( status.equals( Const.STATUS_WAIT ) ) {
			// Dao nguoc ban co lai va doi cho
			normalDirection = false;

			initListQuanCoStatus( normalDirection );

			// Dao nguoc vi tri quan co trong list
			ArrayList<ChessBoardInfo> listInfo2 = new ArrayList<ChessBoardInfo>();

			for( int i = listInfo.size() - 1; i >= 0; i-- ) {
				listInfo2.add( listInfo.get( i ) );
			}

			listInfo = listInfo2;

			symmetryFlag = true;
		}

		if ( !becomeAViewer && !isPlayer && status.equals( Const.STATUS_RUN ) ) {
			normalDirection = true;
			initListQuanCoStatus( normalDirection );
			becomeAViewer = true;
			symmetryFlag = true;
		}

		if ( status.equals( Const.STATUS_IDLE ) ) {
			taiHienFlag = true;
			symmetryFlag = false;
		}

		if ( taiHienFlag == true ) {

			if( symmetryFlag == true ) {
				for ( ChessBoardInfo info : listInfo ) {
					Rectangle rect = board.getRect( info.x, info.y );
					rect = board.makeSymmetry( rect );
					info.x = rect.x;
					info.y = rect.y;
				}
			}

			// Tái hiện lại bàn cờ
			listQuanCoStatus.taiHienListQuanCo( listInfo, normalDirection );
		}

		listQuanCoStatus.addHistory();
//		repaint( listQuanCoStatus.getRepaintArea() );
		repaint();
	}

	private void doInitOrReset() {
		historyForRepaint.clear();

		initTrangThaiBanCo();

		player2Timer.reset();
		player1Timer.reset();

		normalDirection = true;
		initListQuanCoStatus( normalDirection );

//		repaint( board.getRepaintOnlyActiveBoard() );
		repaint();
	}

	private void doRunning() {

		// Dieu khien dong ho
		player1Timer.setRemainTime( player1RemainTime );
		player2Timer.setRemainTime( player2RemainTime );

		if( thisTurnIsPlayer2sTurn == Const.TRUE ) {
			player1Timer.pause();
			player2Timer.resume();
		}else {
			player1Timer.resume();
			player2Timer.pause();
		}
	}

	private void doEnd() {
		// Dung dem dong ho
		player2Timer.pause();
		player1Timer.pause();

		if( whosWon != Const.UNDEFINE_VALUE ) {
			if ( isPlayer ) {
				if ( whosWon == playerColor ) {
					message = Msg.MSG_BAN_DA_THANG;
				}
				// Neu la mot nguoi choi thoat ra ngoai
				// hoac het luot di
				// hoac chieu het doi phuong
				else {
					message = Msg.MSG_BAN_DA_THUA;
				}
			} else {
				String name = player1Name;
				if(whosWon == QuanCo.QUAN_TRANG) {
					name = player2Name;
				}
				message = name + " Thang";
			}

			listQuanCoStatus.getRepaintArea().add( board.getMessageArea() );
		}
	}

	private void processWinLoseWhenExit() {
			isPlayer = false;
			onGameFlag = false;
			btInOut.setText( Const.BUTTON_LABEL_NHAP );

			String xml = "";

			// Neu dang doi hoac neu la chu ban co roi khoi ban ma luc do da het co thi reset lai
			if( status.equals( Const.STATUS_WAIT ) || ( isTablesOwner == Const.TRUE && status.equals( Const.STATUS_END ) ) ) {
				if( isTablesOwner == Const.TRUE ) {
					player1Name = player2Name;
				}

				player2Name = "";

				xml = listQuanCoStatus.getInitStatusOfBoard( Const.PROCESS_PLAY_SHOGI_RESET_BOARD, user, isTablesOwner, player1Name, player2Name );
			}

			// Neu dang danh co thi xu ly thang thua
			else {
				PlayersInfo playerInfo = new PlayersInfo( roomId, tableId, player1Name, player2Name, isTablesOwner );

				if( status.equals( Const.STATUS_RUN ) ) {
					if( playerColor == QuanCo.QUAN_DEN ) {
						playerInfo.setWhosWon( QuanCo.QUAN_TRANG );
					}else {
						playerInfo.setWhosWon( QuanCo.QUAN_DEN );
					}
				}

				xml = XMLHelper.convertListObjectToXML( playerInfo, Const.PROCESS_PLAY_SHOGI_LEFT_TO_TABLE, PlayersInfo.class );
			}

			clientUtil.sendBroadcastMessage( xml );
			// TODO
			mListener.refreshMainBoard();
		}

	/**
	 * Ve lai nhung vung can thiet
	 *
	 * @param repaintArea
	 */
	private void repaint( ArrayList<Rectangle> repaintArea ) {
		for ( Rectangle rect : repaintArea ) {
			repaint( rect.x, rect.y, rect.width + 1, rect.height + 1 );
		}
	}

	private void changeToViewCurrentBoardMode() {
		showHistoryFlag = false;
	}

	private void changeToViewHistoryMode() {
		showHistoryFlag = true;
	}

	TimerListener stopWatchListener = new TimerListener() {

		@Override
		public void timeZero() {
			PlayersInfo playerInfo = new PlayersInfo( roomId, tableId, player1Name, player2Name, isTablesOwner );

			if( status.equals( Const.STATUS_RUN ) ) {
				if( playerColor == QuanCo.QUAN_DEN ) {
					playerInfo.setWhosWon( QuanCo.QUAN_TRANG );
				}else {
					playerInfo.setWhosWon( QuanCo.QUAN_DEN );
				}
			}

			String xml = XMLHelper.convertListObjectToXML( playerInfo, Const.PROCESS_PLAY_SHOGI_WIN_LOSE_ACTION, PlayersInfo.class );
			clientUtil.sendBroadcastMessage( xml );
		}
	};

}